<?php

set_time_limit(0);

/**
 * Description of GenerateAction
 *
 * @author Magno
 */
class GeneratorAction extends BaseAction{

    public static $VIEW_GENERATOR = 'view/steps/';

    public function GeneratorAction(){
        parent::__construct();
    }

    public function getView(){
        return GeneratorAction::$VIEW_GENERATOR;
    }

    public function index() {          
        parent::show('view/index.tpl');
    }

    public function isLastStep($step){
        if($step == 9) 
            return true; 
        return false;
    }

    /**
     * Salva o arquivo (.sql) e gera os Objetos Metadados,
     * Redirecionando para o primeiro passo
     */
    public function saveFile(){
        if(!isset ($_FILES["file"]))
            throw new Exception("Arquivo Não Encontrado!!!");

        $params = parent::getValueSession('params');
        if($params == null)
             $params = array();

        $params[Constantes::$PARAM_PROJECT_NAME] = str_replace(" ", "", parent::getValueInput('projectName'));

        $fileString = file_get_contents($_FILES["file"]["tmp_name"]);

        $fileString = str_replace("`", "", $fileString);

        $tbStManager = new TableStringManager($fileString);
        $tablesMeta = $tbStManager->generateAllTableMeta();
        parent::setValueSession('tablesMeta', $tablesMeta);
        parent::setValueSession('params', $params);
        parent::redirect('GeneratorAction.steps');
        
    }

    /**
     * Avança para o próximo passo
     * @param int $step - Passo Atual
     */
    public function nextStep($step){

        $execute = "executeStep$step";
        $this->$execute();
        $step = intval($step)+1;
        
        if(!$this->isLastStep($step)){
            $this->loadStep($step);
        }else{
            parent::setValueOutput('step', $step);
            echo parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'lastStep.tpl');
        }        
    }

    /**
     * Carrega um determinado passo (função preparada para usar ajax)
     * @param int $step - Passo a ser carregado
     */
    public function loadStep($step){        
        $prepare = "prepareStep$step";
        parent::setValueOutput('step', $step);
        echo $this->$prepare();
    }

    /**
     * Carrega uma Classe para pré-visualização
     * @param String $type - Tipo de classe (bean, dao, service)
     * @param String $table - Nome da Tabela correspondente a classe
     */
    public function loadClass($type, $table){
        
        $tablesMeta = parent::getValueSession('tablesMeta');
        $params = parent::getValueSession('params');
        
        $phpCode = true;
        
        switch ($type) {
            case "bean":
                $generator = new BeanGenerator($tablesMeta[$table],$params);
                break;
            case "dao":               
                $generator = new DAOGenerator($tablesMeta[$table],$params);
                break;
            case "service":
                $generator = new ServiceGenerator($tablesMeta[$table],$params);
                break;
            case "action":
                $generator = new ActionGenerator($tablesMeta[$table],$params);
                break;
            case "view":
                $view = ucfirst(parent::getValueInput('view'))."ViewGenerator";
                $generator = new $view($tablesMeta[$table], $params);
                $phpCode = false;
                break;
        }

        $code = $generator->generate();
        
        if($phpCode)
            echo highlight_string($code,true);
        else
            echo Util::xmlHighlight($code);
        
    }

    /**
     * Só redireciona para o primeiro passo
     */
    public function steps(){
        
        if(parent::getValueSession('tablesMeta') == null){
            parent::redirect('GeneratorAction.index');
            return '';
        }
        $params = parent::getValueSession('params');
        parent::setValueOutput('projectName', $params[Constantes::$PARAM_PROJECT_NAME]);
        $this->prepareStep1();       
        parent::setValueOutput('step', 1);
        parent::show(GeneratorAction::$VIEW_GENERATOR.'index.tpl');
    }

    /**
     * Prepara o 1º Passo:
     *  - Prepara o formulario, para q sejam informados, caso exista,
     *  heranças entre as tabelas
     *
     */
    public function prepareStep1(){
        $tablesMeta = parent::getValueSession('tablesMeta');
        $fksHeranca = array();

        foreach ($tablesMeta as $tb) {

            $heranca = false;

            foreach ($tb->getFKReferences() as $fk){
                foreach ($fk->getAttributes() as $att){
                    if($att->isPrimaryKey()){
                        $heranca = true;
                        break;
                    }else{
                        $heranca = false;
                        break;
                    }
                }

                if($heranca)
                    $fksHeranca[] = $fk;
            }
        }

        
        parent::setValueOutput('fksHeranca', $fksHeranca);
        return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step1.tpl');
    }

    /**
     * Salva as heranças informadas
     */
    public function executeStep1(){
        $tablesMeta = parent::getValueSession('tablesMeta');
        foreach ($tablesMeta as $tb) {

            $tbName = $tb->getName();

            foreach ($tb->getFKReferences() as $fk){
                foreach ($fk->getAttributes() as $att){
                    if($att->isPrimaryKey()){
                        
                        $valForm = parent::getValueInput($tbName.':'.$fk->getName());
                        
                        if(isset ($valForm) && strcmp($valForm, "true") == 0){
                            $fk->setExtends(true);
                            break;                        
                        }
                    }
                }
            }
            
        }
        
        parent::setValueSession('tablesMeta', $tablesMeta);        
    }

    /**
     * Prepara o 2º Passo:
     * - Prepara o formulario, para q sejam informados os atributos mais
     * importantes de cada tabela
     */
    public function prepareStep2(){

        $tablesMeta = parent::getValueSession('tablesMeta');

        parent::setValueOutput('tablesMeta', $tablesMeta);
        return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step2.tpl');

    }

    /**
     * Salva os atributos mais importantes de cada tabela
     */
    public function executeStep2(){
        $tablesMeta = parent::getValueSession('tablesMeta');
        foreach ($tablesMeta as $tb) {

            $tbName = $tb->getName();

            foreach ($tb->getAttributes() as $att){
                
                $valForm = parent::getValueInput($tbName.':'.$att->getName());
                
                if($att->isPrimaryKey() || (isset ($valForm) && strcmp($valForm, "true") == 0)){
                    $att->setImportant(true);
                }else{
                    $att->setImportant(false);
                }
            }
            
        }
        
        parent::setValueSession('tablesMeta', $tablesMeta);
    }

    /**
     * Prepara o 3º Passo - Pré visualização das Classes     
     */
    public function prepareStep3(){

        $tablesMeta = parent::getValueSession('tablesMeta');

        parent::setValueOutput('tablesMeta', $tablesMeta);
        return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step3.tpl');

    }

    public function executeStep3(){

    }
    
    /**
     * Prepara o 4º Passo:
     * - Prepara o formulario, para q sejam informados os cadastros
     */
    public function prepareStep4(){

        $tablesMeta = parent::getValueSession('tablesMeta');

        parent::setValueOutput('tablesMeta', $tablesMeta);
        return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step4.tpl');

    }
    /**
     * Salvando Tabelas q irão ter CRUD
     */
    public function executeStep4(){
        $tablesMeta = parent::getValueSession('tablesMeta');
        foreach ($tablesMeta as $tb) {

            $valForm = parent::getValueInput($tb->getName());
                
            if(isset ($valForm) && strcmp($valForm, "true") == 0){
                $tb->setCrud(true);
            }else{
                $tb->setCrud(false);
            }
        }
        
        parent::setValueSession('tablesMeta', $tablesMeta);
    }
    
    /**
     * Prepara o 5º Passo:
     * - Prepara o formulario, para q sejam informados os relacionametos
     * combo ou incluir form da fk
     */
    public function prepareStep5(){

        $tablesMeta = parent::getValueSession('tablesMeta');

        parent::setValueOutput('tablesMeta', $tablesMeta);
        return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step5.tpl');

    }
    /**
     * Salvando se o relacionamento é combo ou form incluir form da fk
     */
    public function executeStep5(){
        $tablesMeta = parent::getValueSession('tablesMeta');
        foreach ($tablesMeta as $tb) {
            
            if(count($tb->getFKReferences()) > 0){
            
                $tbName = $tb->getName();

                foreach ($tb->getFKReferences() as $fk){

                    $valForm = parent::getValueInput($tbName.':'.$fk->getName());
                    if(isset ($valForm))
                        $fk->setTypeForm($valForm);
                    
                }
            }
        }
        
        parent::setValueSession('tablesMeta', $tablesMeta); 
    }
    
    /**
     * Prepara o 6º Passo:
     * - Prepara o formulario, para q sejam informados os atributos display dos
     * possiveis combos
     */
    public function prepareStep6(){

        $tablesMeta = parent::getValueSession('tablesMeta');
        $tablesCombo = array();
        
        foreach ($tablesMeta as $tb) {
            foreach ($tb->getFKReferences() as $fk) {
                 
                if(strcmp($fk->getTypeForm(), Constantes::$TYPE_FORM_COMBO) == 0){
                     $tablesCombo[$fk->getTableReference()->getName()] = $fk->getTableReference();                     
                 }
            }
            
        }
        
        if(count($tablesCombo) > 0){
        
            parent::setValueOutput('tablesMeta', $tablesCombo);
            return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step6.tpl');
        
        }        
        else{
            return $this->loadStep(7);
        }

    }
    /**
     * Salvando os atributos display do combo
     */
    public function executeStep6(){
        $tablesMeta = parent::getValueSession('tablesMeta');
        foreach ($tablesMeta as $tb) {
            
            $value = parent::getValueInput($tb->getName());
            if($value != null){
               $value = explode(":", $value);
               
               foreach ($tb->getAttributes() as $attCb) {
                   if(strcmp($value[1], $attCb->getName()) == 0)
                       $attCb->setComboDisplay(true);
                   else
                       $attCb->setComboDisplay(false);
               }
               
            }
            
        }
        
        parent::setValueSession('tablesMeta', $tablesMeta); 
    }

    /**
     * Prepara o 7º Passo:
     * - Prepara o formulario, para q sejam informados os relacionametos
     * combo ou incluir form da fk
     */
    public function prepareStep7(){
        parent::setValueOutput('params', parent::getValueSession('params'));
        return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step7.tpl');
    }
    
    /**
     * Salvando se o relacionamento é combo ou form incluir form da fk
     */
    public function executeStep7(){
         $params = parent::getValueSession('params');
         if($params == null)
             $params = array();

         $incValidate = parent::getValueInput('incValidate');
         if($incValidate != null && strcmp($incValidate, "true") == 0)
             $incValidate = true;
         else
             $incValidate = false;

         $incCss = parent::getValueInput('incCss');
         if($incCss != null && strcmp($incCss, "true") == 0)
             $incCss = true;
         else
             $incCss = false;
         
         $incMenu = parent::getValueInput('incMenu');
         if($incMenu != null && strcmp($incMenu, "true") == 0)
             $incMenu = true;
         else
             $incMenu = false;

         $params[Constantes::$PARAM_INCLUDE_VALIDADE] = $incValidate;
         $params[Constantes::$PARAM_INCLUDE_CSS] = $incCss;
         $params[Constantes::$PARAM_INCLUDE_MENU] = $incMenu;
         
         parent::setValueSession('params', $params);

    }

    /**
     * Prepara o 8º Passo - Pré visualização das Actions e Views
     */
    public function prepareStep8(){

        $tablesMeta = parent::getValueSession('tablesMeta');

        parent::setValueOutput('tablesMeta', $tablesMeta);
        return parent::getHtml(GeneratorAction::$VIEW_GENERATOR.'step8.tpl');

    }

    public function executeStep8(){

    }

    public function prepareProjectDownload(){

        $tablesMeta = parent::getValueSession('tablesMeta');
        $params = parent::getValueSession('params');

        foreach ($tablesMeta as $tableMeta) {

            $beanGenerator = new BeanGenerator($tableMeta,$params);
            $daoGenerator = new DAOGenerator($tableMeta,$params);
            $serviceGenerator = new ServiceGenerator($tableMeta,$params);

            /** ViewsGenerators Comuns a Todos **/
            $formComboViewGenerator = new FormComboViewGenerator($tableMeta, $params);
            $formIncludeViewGenerator = new FormIncludeViewGenerator($tableMeta, $params);
            $detalhesIncludeViewGenerator = new DetalhesIncludeViewGenerator($tableMeta, $params);
            
            $beanGenerator->generateFile();
            $daoGenerator->generateFile();
            $serviceGenerator->generateFile();
            
            $formComboViewGenerator->generateFile();
            $formIncludeViewGenerator->generateFile();
            $detalhesIncludeViewGenerator->generateFile();
            

            if($tableMeta->isCrud()){
                
                $actionGenerator = new ActionGenerator($tableMeta,$params);
                
                /** ViewsGenerators Soh Pra quem tem Cadastro **/
                $cadastroViewGenerator = new CadastroViewGenerator($tableMeta, $params);
                $detalhesViewGenerator = new DetalhesViewGenerator($tableMeta, $params);
                $listarViewGenerator = new ListarViewGenerator($tableMeta, $params);
                $tabelaViewGenerator = new TabelaViewGenerator($tableMeta, $params);
                $formBuscaViewGenerator = new FormBuscaViewGenerator($tableMeta, $params);
                
                $actionGenerator->generateFile();
                $cadastroViewGenerator->generateFile();
                $detalhesViewGenerator->generateFile();
                $listarViewGenerator->generateFile();
                $tabelaViewGenerator->generateFile();
                $formBuscaViewGenerator->generateFile();
                
                               
            }

        }
        
        if($params[Constantes::$PARAM_INCLUDE_MENU]){
            $menuViewGenerator = new MenuViewGenerator($tablesMeta, $params);
            $menuViewGenerator->generateFile();
        }

        

        
        $name = $params[Constantes::$PARAM_PROJECT_NAME];
        $directory = 'temp_gen/'.$name;

        $this->copyIncludeDir('temp_gen/include','temp_gen/'.$name);
        $this->replaceHtaccess('temp_gen/'.$name.'/.htaccess', $name);
        
        include 'include/php/compactador.php';

    }
    
    private function copyIncludeDir($diretorio, $destino){                
        
        if ($destino{strlen($destino) - 1} == '/') {
            $destino = substr($destino, 0, -1);
        }
        if (!is_dir($destino)) 
            mkdir($destino, 0755, true);
        

        $folder = opendir($diretorio);

        while ($item = readdir($folder)) {
            if ($item == '.' || $item == '..') {
                continue;
            }
            if (is_dir("{$diretorio}/{$item}")) {
                $this->copyIncludeDir("{$diretorio}/{$item}", "{$destino}/{$item}");
            } else {
                copy("{$diretorio}/{$item}", "{$destino}/{$item}");
            }
        }
    }
    
    private function replaceHtaccess($dir, $projectName){
        $htaccess = file_get_contents($dir);
        $htaccess = str_replace(":projectName", $projectName, $htaccess);
        $fp = fopen($dir, "w+");
        fwrite($fp, $htaccess);
        fclose($fp);
    }
}
?>
